/*
 * Copyright 2002-2021 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.fjsei.yewu.device;

import com.querydsl.core.BooleanBuilder;
import graphql.relay.Connection;
import graphql.schema.DataFetchingEnvironment;
import md.cm.geography.Adminunit;
import md.cm.geography.AdminunitRepository;
import md.cm.geography.Village;
import md.cm.geography.VillageRepository;
import md.cm.unit.Division;
import md.cm.unit.Unit;
import md.specialEqp.*;
import md.specialEqp.inspect.Detail;
import md.specialEqp.inspect.Task;
import md.specialEqp.type.*;
import org.fjsei.yewu.graphql.DbPageConnection;
import org.fjsei.yewu.input.DeviceCommonInput;
import org.fjsei.yewu.jpa.PageOffsetFirst;
import org.fjsei.yewu.resolver.Comngrql;
import org.fjsei.yewu.util.Tool;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;
import org.springframework.graphql.data.method.annotation.Argument;
import org.springframework.graphql.data.method.annotation.MutationMapping;
import org.springframework.graphql.data.method.annotation.SchemaMapping;
import org.springframework.graphql.execution.BatchLoaderRegistry;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import java.util.List;
import java.util.UUID;

/**默认Unit模型的属性； graphQL接口;
 * 底下批处理方案还不是一种的。 注释掉的也是1个方案。
 * 每一个graphQL的Object对象type都需单独声明一个XxxController implements IdMapper<type> {} 否则Id都无法转换成Relay要的GlobalID的。
 * 报错：无法使用 implements IdMapper<Eqp>
 * */

@Controller
public class PipelineController extends Comngrql {
	@PersistenceContext(unitName = "entityManagerFactorySei")
	private EntityManager emSei;
	private final Equipments equipments;
	private final AdminunitRepository adminunitRepository;
	private final VillageRepository villageRepository;
	private final PipingUnitRepository pipingUnitRepository;

	public PipelineController(BatchLoaderRegistry registry, Equipments equipments, AdminunitRepository adminunitRepository, VillageRepository villageRepository, PipingUnitRepository pipingUnitRepository) {
		this.equipments = equipments;
		this.adminunitRepository = adminunitRepository;
		this.villageRepository = villageRepository;
		this.pipingUnitRepository = pipingUnitRepository;
	}

	//替代 *.graphqls 模型文件上的@dbpage注解：Spring Graphql直接可以调用这里的。 graphQL接口名字是不允许重载的； 旧版本没有Pipeline typeObj,参数；
//	@SchemaMapping(typeName="Pipeline", field="cell_list" )
//	public Connection<PipingUnit> getCell_list(Pipeline typeObj,String orderBy, boolean asc,DeviceCommonInput where,int first,String after,int last,String before,DataFetchingEnvironment env) {
	@SchemaMapping
	public Connection<PipingUnit> cell_list(Pipeline pipeline,@Argument String orderBy,@Argument Boolean asc,@Argument DeviceCommonInput where,@Argument Integer first,
			@Argument String after,@Argument Integer last,@Argument String before, DataFetchingEnvironment env) {
		DbPageConnection<PipingUnit> connection=new DbPageConnection(env);
		//从Relay参数来反推出offset/limit;
		int offset=connection.getOffset();
		int limit=connection.getLimit();
		Pageable pageable;
		if (!StringUtils.hasLength(orderBy))
			pageable = PageOffsetFirst.of(offset, limit);
		else
			pageable = PageOffsetFirst.of(offset, limit, Sort.by(asc ? Sort.Direction.ASC : Sort.Direction.DESC, orderBy));
		QPipingUnit qm = QPipingUnit.pipingUnit;
		BooleanBuilder builder = new BooleanBuilder();
		UUID contId;
		Class<?> ptype=env.getSource().getClass();
		//跳转接口模式: @dbpage; 从Pipeline内省而来的，并非直接给出参数字段去查询的独立接口Query模式。
		if(Pipeline.class== ptype )
		{
			Pipeline parent=env.getSource();
			contId= parent.getId();
			builder.and(qm.pipe.id.eq(contId));
		}
		Slice<PipingUnit> rpage= (Slice<PipingUnit>)pipingUnitRepository.findAll(builder,pageable);
		List<PipingUnit> listO=(List<PipingUnit>) rpage.toList();
		//实际上SimpleListConnection也是DataFetcher<>的。内部直接提供简单cursor功能并且自己从env提取Relay参数。
		//SimpleListConnection()的输入必须是List必须是所有的node而且不能已经做了分页，
		// 给下面必须是完整Relay全部数据,SimpleListConnection自己提供游标和分页能力。
		return connection.setListData(listO).get(env);
	}

}

